#! /usr/bin/env python
# -*- coding: utf-8 -*-

# Author: Hui Chen <usa.chen [at] gmail.com>
# PDFWP is a CGI program for rendering PDF digest of WordPress weblog. 
# This software is published under GPL v3
# At current stage, only simplified and traditional Chinese PDFis can be generated, but you 
# can add your own languages by changing settings below in the configuration section.

# Installation:
# 	1. Read "system requirement" below
#	2. Copy index.cgi, mkpdf.sh, digest.css, id.txt into a sub-directory of your webroot 
#	3. Setup 'tex' and 'pdf' folders under the fold where this CGI script exists
#	4. Make id.txt, 'tex' and 'pdf' writable and index.cgi and mkpdf executable by www user
#	5. Change variables' values in configuration section. 
#	6. For debugging, uncomment the 'import cgitb;cgitb.enable()' line and check out temporary
#	   files under /tmp/, 'tex' and 'pdf' directories.

# System requirement:
#	Encoding of WP tables in database has to be UTF-8
# 	Utilities:
#		latex, pdflatex, iconv(convertion between UTF-8 and GBK/Big5) 
#		and zh-autoconvert (for convertion between S.Chinese and T.Chinese)
# 	LaTeX packages:
#		CJK, amssymb, amsmath, indentfirst, hyperref, mathpazo(optional)
#		and CJK fonts (Song, Hei and Kai ti) for simplified and traditional Chinese

#import cgitb; cgitb.enable() # only uncomment this line while debugging
import cgi
import codecs
import sys
import MySQLdb
import re
import os

################### configuration ####################

# please change web server's user root in mkpdf.sh script

# database setup
db_host="localhost"
db_user="wpuser"
db_password="password"
db_name="wpdb"
post_content_minimal_byte=1000 # minimal bytes for post that appears in selection list (can be turned off)

# LaTeX setup

simplified_chinese_CJKfont_song="song" # change these font to those installed in your system
simplified_chinese_CJKfont_hei="hei"
simplified_chinese_CJKfont_kai="kai"
traditional_chinese_CJKfont_song="bsmi"
traditional_chinese_CJKfont_hei="heiti"
traditional_chinese_CJKfont_kai="bkai"
pdf_book_title=u'《博客文摘》'
use_mathpazo_font=True # whether use mathpazo package in LaTeX
max_art=50 # maximum number of PDFs to be saved on server (then it rotates and overwrites the first one)

# webpage rendering setup
webpage_title=u"博客文摘"
webpage_heading=u"博客文摘生成器"
pdf_name_pre="blog"
article_url_template="http://www.myblog.com/?p=%d"
counter_code=''' ''' # add your counter code here

################# you normally don't need to change anything below ####################

root_dir=os.getcwd()+'/'

def myp(a):
	sys.stdout.write( a.encode("UTF-8"))

cgiform = cgi.FieldStorage()

print u'Content-type: text/html; charset="UTF-8"\n'

myp(u'''<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>'''+webpage_title+'''</title>
<link rel="stylesheet" href="digest.css" type="text/css" media="screen" />
<script language="javascript" type="text/javascript">
function Select1(Select)
{
    for (var n=0, k=0; k < document.forms[0].length; n++)
        if (document.forms[0].elements[n].name=="article1" && document.forms[0].elements[n].type=='checkbox')
            document.forms[0].elements[n].checked=Select;
    return false;   
}
function Select2(Select)
{
    for (var n=0, k=0; k < document.forms[0].length; n++)
        if (document.forms[0].elements[n].name=="article2" && document.forms[0].elements[n].type=='checkbox')
            document.forms[0].elements[n].checked=Select;
    return false;   
}
</script>
</head>

<body bgcolor="#FFFFFF" text="#000000" link="#0000ff" vlink="#000080" >
<div class="heading"><h1>'''+webpage_heading+'''</h1></div>

<div class="selectform">
''')

art=[]
if (cgiform.has_key("article1")):
	if (type(cgiform["article1"]) == type([])):
		for i1 in cgiform["article1"]:
			art.append(int(i1.value))
	else:
		art.append(int(cgiform["article1"].value))
if (cgiform.has_key("article2")):
	if (type(cgiform["article2"]) == type([])):
		for i1 in cgiform["article2"]:
			art.append(int(i1.value))
	else:
		art.append(int(cgiform["article2"].value))

cat=[]
if (cgiform.has_key("cat")):
	if (type(cgiform["cat"]) == type([])):
		for i1 in cgiform["cat"]:
			cat.append(int(i1.value))
	else:
		cat.append(int(cgiform["cat"].value))

desc=0
if (cgiform.has_key("desc")):
	desc=1

if (cgiform.has_key("gen_sc") or cgiform.has_key("gen_tc")):
	gen=1
else:
	gen=0

tc=0
if (cgiform.has_key("gen_tc")):
	tc=1

if (cgiform.has_key("dis")):
	dis=1
else:
	dis=0

if (cgiform.has_key("lart")):
	lart=1
else:
	lart=0

if (cgiform.has_key("id")):
	if (type(cgiform["id"]) == type([])):
		id=int(cgiform["id"][0].value)
	else:
		id=int(cgiform["id"].value)
	if (id>max_art or id <=0):
		id=1
else:
	if (gen):
		f=open('id.txt')
		id=f.readline()
		id=int(id)+1
		f.close()
		if (id>max_art or id <=0):
			id=1
		f=open('id.txt', 'w')
		f.write(str(id)+'\n')
		f.close()
	else:
		id=0

if (lart==0 and (not gen) and (not dis) and (not len(art))):
	lart=1

if (id):
	utf8_sc_filename="tex/"+pdf_name_pre+"-utf8-sc-id"+str(id)+".tex"
	utf8_sc_dispname=""+pdf_name_pre+"-utf8-sc-id"+str(id)+".tex"
	utf8_tc_tempname="tex/"+pdf_name_pre+"-utf8-tc-temp-id"+str(id)+".tex"
	utf8_tc_tempname1="tex/"+pdf_name_pre+"-utf8-tc-temp1-id"+str(id)+".tex"
	utf8_tc_filename="tex/"+pdf_name_pre+"-utf8-tc-id"+str(id)+".tex"
	utf8_tc_dispname=""+pdf_name_pre+"-utf8-tc-id"+str(id)+".tex"

	pdf_sc_filename="pdf/"+pdf_name_pre+"-gbk-sc-id"+str(id)+".pdf"
	pdf_sc_dispname=""+pdf_name_pre+"-gbk-sc-id"+str(id)+".pdf"
	pdf_tc_filename="pdf/"+pdf_name_pre+"-utf8-tc-id"+str(id)+".pdf"
	pdf_tc_dispname=""+pdf_name_pre+"-utf8-tc-id"+str(id)+".pdf"

	gbk_filename="tex/"+pdf_name_pre+"-gbk-sc-id"+str(id)+".tex"
	gbk_dispname=""+pdf_name_pre+"-gbk-sc-id"+str(id)+".tex"
	gbk_filename1="tex/"+pdf_name_pre+"-gbk1-sc-id"+str(id)+".tex"
	big5_filename="tex/"+pdf_name_pre+"-big5-tc-id"+str(id)+".tex"
	big5_dispname=""+pdf_name_pre+"-big5-tc-id"+str(id)+".tex"
	big5_filename1="tex/"+pdf_name_pre+"-big51-tc-id"+str(id)+".tex"

else:
	utf8_sc_filename="tex/"+pdf_name_pre+"-utf8-sc.tex"
	utf8_sc_dispname=""+pdf_name_pre+"-utf8-sc.tex"
	utf8_tc_tempname="tex/"+pdf_name_pre+"-utf8-tc-temp-id.tex"
	utf8_tc_tempname1="tex/"+pdf_name_pre+"-utf8-tc-temp1-id.tex"
	utf8_tc_filename="tex/"+pdf_name_pre+"-utf8-tc.tex"
	utf8_tc_dispname=""+pdf_name_pre+"-utf8-tc.tex"

	pdf_sc_filename="pdf/"+pdf_name_pre+"-gbk-sc.pdf"
	pdf_sc_dispname=""+pdf_name_pre+"-gbk-sc.pdf"
	pdf_tc_filename="pdf/"+pdf_name_pre+"-utf8-tc.pdf"
	pdf_tc_dispname=""+pdf_name_pre+"-utf8-tc.pdf"

	gbk_filename="tex/"+pdf_name_pre+"-gbk-sc.tex"
	gbk_dispname=""+pdf_name_pre+"-gbk-sc.tex"
	gbk_filename1="tex/"+pdf_name_pre+"-gbk1-sc.tex"
	big5_filename="tex/"+pdf_name_pre+"-big5-tc.tex"
	big5_dispname=""+pdf_name_pre+"-big5-tc.tex"
	big5_filename1="tex/"+pdf_name_pre+"-big51-tc.tex"

db=MySQLdb.connect(host=db_host, user=db_user, passwd=db_password, db=db_name, charset="utf8")

c=db.cursor()

mysql_query="select post_title, post_date, post_content, ID from wp_posts where post_status='publish' and post_author='1' "
if (lart):
	mysql_query=mysql_query+"and length(post_content)>"+str(post_content_minimal_byte)
mysql_query=mysql_query+" order by post_date"

if (desc):
	mysql_query = mysql_query+' desc'

c.execute(mysql_query)

r=c.fetchall()

mysql_query="select post_id, category_id from wp_post2cat"

c.execute(mysql_query)

r2=c.fetchall()

for kkk in r2:
	if (cat.count(kkk[1])):
		art.append(int(kkk[0]))

if (art !=[] and gen):
	if (not tc):
		f=codecs.open(utf8_sc_filename, "w", "utf8")
		f_gbk=codecs.open(gbk_filename1, "w", "utf8")
	else:
		f_big5=codecs.open(big5_filename1, "w", "utf8")
		f_tc=codecs.open(utf8_tc_tempname1, "w", "utf8")

	n=30

	pre='''%To compile, run following twice:
%pdflatex '''+utf8_sc_dispname+''' 
\documentclass[12pt, a4paper]{article}
\usepackage{amssymb,amsmath}
'''
	if (use_mathpazo_font):
		pre=pre+''' \usepackage{mathpazo}
'''
	pre=pre+'''\usepackage{CJK}
\usepackage{indentfirst}
\usepackage[colorlinks,plainpages=false,bookmarks=false]{hyperref}

\setlength{\\topmargin}{-.1in}
\setlength{\\textheight}{8.9in}
\setlength{\hoffset}{-.5in}
\setlength{\\textwidth}{6.5in}
\linespread{1.3}

\\newcommand{\myquotefont}{\CJKfamily{'''+ simplified_chinese_CJKfont_kai+'''}}
\\newcommand{\mysectionfont}{\CJKfamily{'''+ simplified_chinese_CJKfont_hei+'''}}

\\begin{document}
\\begin{CJK*}{UTF8}{'''+ simplified_chinese_CJKfont_song+'''}
\CJKindent
\CJKtilde
'''
	if (len(art)>1):
		pre=pre+'''{\mysectionfont
\\title{\\bf \Huge '''+ pdf_book_title +'''} 
\\author{}
\date{}
\maketitle 
\\renewcommand{\contentsname}{'''+u'目录'+'''}
\\tableofcontents
\\newpage
}
'''
	pre=pre+'''
\setlength{\parskip}{1ex plus 0.5ex minus 0.2ex}

'''
	if (not tc):
		f.write(pre)
		pre_gbk=pre.replace("UTF8", "GBK")
		pre_gbk=pre_gbk.replace("utf8", "gbk")
		f_gbk.write(pre_gbk)
	else:
		pre_big5=pre.replace("UTF8", "Bg5")
		pre_big5=pre_big5.replace("utf8", "big5")
		pre_big5=pre_big5.replace("{"+ simplified_chinese_CJKfont_song+"}", "{"+ traditional_chinese_CJKfont_song+"}")
		pre_big5=pre_big5.replace("{"+ simplified_chinese_CJKfont_hei+"}", "{"+ traditional_chinese_CJKfont_hei+"}")
		pre_big5=pre_big5.replace("{"+ simplified_chinese_CJKfont_kai+"}", "{"+ traditional_chinese_CJKfont_kai+"}")
		pre_tc=pre.replace("{"+ simplified_chinese_CJKfont_song+"}", "{"+ traditional_chinese_CJKfont_song+"}")
		pre_tc=pre_tc.replace("{"+ simplified_chinese_CJKfont_hei+"}", "{"+ traditional_chinese_CJKfont_hei+"}")
		pre_tc=pre_tc.replace("{"+ simplified_chinese_CJKfont_kai+"}", "{"+ traditional_chinese_CJKfont_kai+"}")
		f_big5.write(pre_big5)
		f_tc.write(pre_tc)

	submystr_url=re.compile(r'<a .*?href="(.*?)">(.*?)</a>')
	submystr_url_remove1=re.compile(r'(<a [^>]*?>)\n' )
	submystr_url_remove2=re.compile(r'\n(</a>)' )
	submystr_img=re.compile(r'<img .*?src="(.*?)".*?>', re.DOTALL)
	submystr_embed=re.compile(r'<embed .*?>', re.DOTALL)
	submystr_table=re.compile(r'<table .*?</table>', re.DOTALL)
	submystr_strong=re.compile(r'<strong>(.*)</strong>')
	submystr_tex_1=re.compile(r'(\$.*?)(\^)(.*?\$)')
	submystr_tex_2=re.compile(r'(\$.*)(\&)(.*\$)')
	submystr_tex_3=re.compile(r'(\$.*)(_)(.*\$)')
	submystr_tex_4=re.compile(r'(\$.*)(%)(.*\$)')
	submystr_tex_5=re.compile(r'(\$.*)(>)(.*\$)')
	submystr_tex_6=re.compile(r'(\$.*)(<)(.*\$)')

	k=0
	for i in r:
		flag=art.count(i[3])
		if ( not flag):
			continue
		if (len(art)>1):
			if (not tc):
				f.write('\section{\mysectionfont %s }\n\n' % (i[0]))
				f_gbk.write('\section{\mysectionfont %s }\n\n' % (i[0]))
			else:
				f_big5.write('\section{\mysectionfont %s }\n\n' % (i[0]))
				f_tc.write('\section{\mysectionfont %s }\n\n' % (i[0]))
		else:
			if (not tc):
				f.write('\section*{\mysectionfont %s }\n\n' % (i[0]))
				f_gbk.write('\section*{\mysectionfont %s }\n\n' % (i[0]))
			else:
				f_big5.write('\section*{\mysectionfont %s }\n\n' % (i[0]))
				f_tc.write('\section*{\mysectionfont %s }\n\n' % (i[0]))
		d=i[1]
		mystr=i[2]
		mystr=mystr.replace('\x0d', '')

		mystr=mystr.replace('$', '\\$')
		mystr=mystr.replace('[tex]', '$')
		mystr=mystr.replace('[/tex]', '$')

		for j in range(1, n):
			mystr=submystr_tex_1.sub(r'\1 kkkqqq1\3', mystr)
		mystr=mystr.replace('^', '\\^{}')
		mystr=mystr.replace('kkkqqq1', '^')

		for j in range(1, n):
			mystr=submystr_tex_2.sub(r'\1 kkkqqq2\3', mystr)
		mystr=mystr.replace('&', '\\&')
		mystr=mystr.replace('kkkqqq2', '&')

		for j in range(1, n):
			mystr=submystr_tex_3.sub(r'\1 kkkqqq3\3', mystr)
		mystr=mystr.replace('_', '\\_')
		mystr=mystr.replace('kkkqqq3', '_')

		for j in range(1, n):
			mystr=submystr_tex_4.sub(r'\1 kkkqqq4\3', mystr)
		mystr=mystr.replace('%', '\\%')
		mystr=mystr.replace('kkkqqq4', '%')

		for j in range(1, n):
			mystr=submystr_url_remove1.sub(r'\1', mystr)
			mystr=submystr_url_remove2.sub(r'\1', mystr)
				
		mystr=mystr.replace('\n', '\n\n')
		mystr=mystr.replace('#', '')
		mystr=mystr.replace('-_-', '')
		mystr=mystr.replace('&8217;', "'")
		mystr=mystr.replace('&lt;', '<')
		mystr=mystr.replace('&gt;', '>')
		mystr=mystr.replace('&amp;', '&')
		mystr=mystr.replace('\\bt', '\\\\bt')
		mystr=mystr.replace('\\lt', '\\\\lt')
		mystr=mystr.replace('<!--more-->', '')
		mystr=mystr.replace('<blockquote>', '{\myquotefont ')
		mystr=mystr.replace('</blockquote>', '}')
		mystr=mystr.replace('<strong>', '{\mysectionfont ')
		mystr=mystr.replace('</strong>', '}')
		mystr=mystr.replace('<li>','')
		mystr=mystr.replace('</li>','')
		mystr=mystr.replace('</embed>','')
		mystr=mystr.replace('\n\n\n','\n\n')
		mystr=mystr.replace('\n\n\n','\n\n')
		mystr=mystr.replace('\n\n\n','\n\n')
		mystr=mystr.replace('\n\n\n','\n\n')
		mystr=mystr.replace('\n\n\n','\n\n')
		
		for j in range(1, n):
			mystr=submystr_url.sub(r'\2\\footnote{url: \1 }', mystr)
			mystr=submystr_img.sub(r'IIImage\\footnote{image: \1}', mystr)
			mystr=submystr_embed.sub('', mystr)
			mystr=submystr_table.sub('', mystr)
		mystr=mystr.replace('IIImage',u'图片')

		for j in range(1, n):
			mystr=submystr_tex_5.sub(r'\1 kkkqqq5\3', mystr)
		mystr=mystr.replace('>', '$>$')
		mystr=mystr.replace('kkkqqq5', '>')

		for j in range(1, n):
			mystr=submystr_tex_6.sub(r'\1 kkkqqq6\3', mystr)
		mystr=mystr.replace('<', '$<$')
		mystr=mystr.replace('kkkqqq6', '<')

		if (not tc):
			f.write(unicode(mystr))
			f.write('\\newpage\n')
			f.write('\n')
			f_gbk.write(unicode(mystr))
			f_gbk.write('\\newpage\n')
			f_gbk.write('\n')
		else:
			f_big5.write(unicode(mystr))
			f_tc.write(unicode(mystr))
			f_big5.write('\\newpage\n')
			f_tc.write('\\newpage\n')
			f_big5.write('\n')
			f_tc.write('\n')

	pre='''
\end{CJK*}

\end{document}
'''

	if (not tc):
		f.write(pre)
		f.close()
		f_gbk.write(pre)
		f_gbk.close()
	else:
		f_big5.write(pre)
		f_tc.write(pre)
		f_big5.close()
		f_tc.close()

	if (not tc):
		os.system("iconv -f utf8 -t gbk -c "+gbk_filename1+" -o "+gbk_filename)
		os.unlink(gbk_filename1)
	else:
		os.system("autob5 -i utf8 < "+big5_filename1+" > "+big5_filename)
		os.system("autob5 -i utf8 < "+utf8_tc_tempname1+" > "+utf8_tc_tempname)
		os.system("iconv -f big5 -t utf8 -c "+utf8_tc_tempname+" -o "+utf8_tc_filename)
		os.unlink(big5_filename1)
		os.unlink(utf8_tc_tempname)
		os.unlink(utf8_tc_tempname1)

	if (not tc):
		os.system("rm -f "+pdf_sc_filename)
		os.system("cp "+gbk_filename+" /tmp/; cd /tmp/; "+root_dir+"mkpdf.sh "+gbk_dispname+" " + pdf_sc_dispname + " "+root_dir+pdf_sc_filename + " > /dev/null & ")
	else:
		os.system("rm -f "+pdf_tc_filename)
		os.system("cp "+utf8_tc_filename+" /tmp/; cd /tmp/; "+root_dir+"mkpdf.sh "+utf8_tc_dispname+" " + pdf_tc_dispname + " "+root_dir+pdf_tc_filename + " > /dev/null & ")

if (art !=[] and gen):
	myp(u'''
PDF下载： ''')
	if (not tc):
		myp(u'''<br>简体中文 <a href="'''+pdf_sc_filename+u'''">'''+pdf_sc_dispname+u'''</a> &nbsp;''')
	else:
		myp(u'''<br>正体中文 <a href="'''+pdf_tc_filename+u'''">'''+pdf_tc_dispname+u'''</a> &nbsp; ''')
	myp(u'''<br>\n生成PDF需要时间，如果选中的文章较多，请等<font style="color:red">大约一分钟</font>后点击下载。生成的PDF文件不会在服务器上保留很长时间。 <br><br>
LaTeX源文件： ''')
	if (not tc):
		myp(u'''<br>GBK码简体 <a href="'''+gbk_filename+u'''">'''+gbk_dispname+u'''</a> &nbsp; 
UTF8码简体 <a href="'''+utf8_sc_filename+u'''">'''+utf8_sc_dispname+u'''</a> &nbsp;''')
	else:
		myp(u'''<br>BIG5碼正体 <a href="'''+big5_filename+u'''">'''+big5_dispname+u'''</a> &nbsp; 
UTF8碼正体 <a href="'''+utf8_tc_filename+u'''">'''+utf8_tc_dispname+u'''</a> &nbsp;''')
	myp(u'''
<br>修改LaTeX文件中的CJK字体后用pdflatex编译<font style="color:red">两次</font>生成PDF文件。
<br><br>\n
''')

if (art !=[]):
	myp(u'''<!-- Select From begins -->
<form name="go" method="post" action="index.cgi">
在下面选文章然后 <input name="dis" value="更新列表" type="submit"> &nbsp; 
确定选择无误后生成 <input name="gen_sc" value="简体中文PDF和LaTeX文档" type="submit"> &nbsp;
或者 <input name="gen_tc" value="正体中文PDF和LaTeX文檔" type="submit"><br>
''')
else:
	myp(u'''<form name="go" method="post" action="index.cgi">
在下面选文章然后 <input name="dis" value="更新列表" type="submit"> <br>
''')

c.execute("select cat_ID, cat_name, category_nicename from wp_categories where category_count!=0 " ) 

r1=c.fetchall()

if (id):
	myp('<input type="hidden" name="id" value="'+str(id)+'">\n')

myp(u'<br>按时间逆序排列 &nbsp; <input type="checkbox" name="desc" ')
if (desc):
	myp('checked')
myp('>\n')

myp(u' &nbsp; 只显示长度大于'+str(post_content_minimal_byte)+u'字节的文章 &nbsp; <input type="checkbox" name="lart" ')
if (lart):
	myp('checked')
myp('><br>\n')

myp(u'<br>选择分类中所有文章 &nbsp; ')
for i2 in r1:
	myp('\n<input type="checkbox" name="cat" value="'+str(i2[0])+'" ')
	myp('> ')
	myp(i2[1])
	myp(' &nbsp; ')
myp('<br>\n')

myp('<br>\n<table cellpadding=10 border=1>\n<tr>\n')
rest=0
if (art !=[]):
	myp('<td align="left" valign="top">\n')
	myp(u'''已经选中的文章列表: &nbsp; <a href="#" onclick="javascript:Select1(true)">全选</a> | <a href="#" onclick="javascript:Select1(false)">全不选</a> <br><br>\n''')
	for ii in r:
		if (art.count(ii[3])):
			myp('<input type="checkbox" name="article1" value="'+str(ii[3])+'" ')
			myp('checked')
			myp('> &nbsp;')
			myp('<a href="'+ (article_url_template % ii[3]) +'" target="_new">'+ii[0]+'</a>')
			myp('<br>\n')
		else:
			rest=rest+1
	myp('<br>\n</td>')

if (art !=[]):
	if (rest) :
		myp('\n<td align="left" valign="top">\n')
		myp(u'''其他文章: &nbsp; <a href="#" onclick="javascript:Select2(true)">全选</a> | <a href="#" onclick="javascript:Select2(false)">全不选</a> <br><br>\n''')
else:
	myp('\n<td>\n')
	myp(u'''请选择文章: &nbsp; <a href="#" onclick="javascript:Select2(true)">全选</a> | <a href="#" onclick="javascript:Select2(false)">全不选</a> <br><br>\n''')

for ii in r:
	if (not art.count(ii[3])):
		myp('<input type="checkbox" name="article2" value="'+str(ii[3])+'" ')
		myp('> &nbsp;')
		myp('<a href="'+ (article_url_template % ii[3]) +'" target="_new">'+ii[0]+'</a>')
		myp('<br>\n')

if (not (art !=[] and (not rest))):
	myp('<br>\n</td>\n')
	
myp('</tr>\n</table>')

myp(u'''\n</form>
<!-- Select Form ends -->

</div>\n\n''')
myp(counter_code)
myp(u'''
</html>
''')
